package Master;

//import sun.rmi.server.Dispatcher;

import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.rmi.registry.Registry;
import java.util.*;

import Master.interfaces.ClientGUI;
import Master.interfaces.InputScreen;

/**
 * Project:    metsysdirg
 * File Name: MasterEngine.java
 * Change History:
 *     ********************************
 *     1.0     5/14/2011    Hengfeng Li
 *         Create the skeleton file
 *     ********************************
 *
 */
public class MasterEngine {
    /*

      This is an coordinator of master.
      Step 1. receive the tasks list from ClientGUI.

      Step 2. add the tasks into a queue

      Step 3. distribute the tasks according to the status of workers

      Step 4. get the status info from worker and send back to display in ClientGUI

     */

    // private TaskPlan taskPlan;
    // private Queue<Task> taskQueue;
    // private ExecutorService threadPool;

    // private Queue<Thread> dispatcherPool;
	
	private InputScreen client_gui;
	private PrintStream default_stdout, default_stderr;
    private final Timer timer;
    
    public static enum AlgorithmFlag {FCFS, COST, TIME};
    public static AlgorithmFlag algorithmFlag = AlgorithmFlag.FCFS;
    private boolean isFirstTaskPlan=true;

    public MasterEngine(){
        timer = new Timer();

    }
    
    public void launchGUI()
    {
    	System.out.println("Launching the GUI...");
    	client_gui = new InputScreen();
    	client_gui.startup(this);
    }

    public void execute(TaskPlan taskPlan){
    	ScheduleAlgorithm scheduleAlgorithm = new ScheduleAlgorithm();
    	//System.out.println("algorithmFlag =" + algorithmFlag);
    	
    	
    	System.out.println("algorithmFlag.ordinal() =" + algorithmFlag.ordinal());
    	
    	//scheduleAlgorithm.fcfsBasedSchedule(taskPlan);
    	switch(algorithmFlag.ordinal()){
    	case 0:
    		System.out.println("FCFS === algorithmFlag.ordinal() =" + algorithmFlag.ordinal());
    	    scheduleAlgorithm.fcfsBasedSchedule(taskPlan);
    		break;
    	case 1:
    		System.out.println("TME === algorithmFlag.ordinal() =" + algorithmFlag.ordinal());
    		scheduleAlgorithm.timeBasedSchedule(taskPlan);
    		break;
    	case 2:
    		System.out.println("COST === algorithmFlag.ordinal() =" + algorithmFlag.ordinal());
    		scheduleAlgorithm.costBasedSchedule(taskPlan);
    		break;
    	}
    
    	// began to run the dispatcher
    	if(this.isFirstTaskPlan)
    	{
    		for(Resource resource : taskPlan.getResources()){
    			System.out.println(this.getClass() + "JJJ :resourceID:"+resource.getID());
                resource.runDispatcher();
                System.out.println(this.getClass() + "WWW :resourceID:"+resource.getID());
    		}
    		
    		System.out.println(this.getClass() + "here 2");
    		this.isFirstTaskPlan=false;
        }
    }
    
    

    public static void main(String[] args) {
    	
    	//System.setProperty("java.security.policy", "local.policy");
        //System.setSecurityManager(new SecurityManager());
    	
        try {
            // get the information about the local host address
            InetAddress address = InetAddress.getLocalHost();
            String hostAddress = address.getHostAddress();
            String hostname = address.getHostName();

            if(args.length == 1) {
                hostAddress = args[0];
            } else if (args.length != 0) {
                System.exit(-1);
            }

            MasterEngine masterEngine = new MasterEngine();
            masterEngine.launchGUI();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private class CountDownTask extends TimerTask {
        int seconds;

        public CountDownTask(int seconds){
            this.seconds = seconds;
        }
        public void run(){
            System.out.println("remaining time : " + seconds);
            if(seconds == 0) {
                timer.cancel();
            }
            seconds--;
        }

    }

    public void cancelTimer(){
        this.timer.cancel();
    }

    public void timeStart(int seconds){
        TimerTask tt = new CountDownTask(seconds);
        timer.schedule(tt, 0, 1000);

    }
    
    public void redirectSystemStreams(OutputStream out)
	{
		default_stdout=System.out;
		default_stderr=System.err;
		
		System.setOut(new PrintStream(out, true));
		System.setErr(new PrintStream(out, true));
	}
	
	public void returnDefaultSystemStreams()
	{
		System.setOut(default_stdout);
		System.setErr(default_stderr);
	}
}
